import os,shelve,time
import requests
import threading
from Crypto.Cipher import AES
from requests.adapters import HTTPAdapter
from PyQt5.QtCore import QThread,pyqtSignal,QObject



class ts_download():
    def __init__(self,tsurl_lists,path,threadnum,key):
        """
        :param tsurl_lists: ts下载地址列表
        :param path: 路径
        :param threadnum: 线程数
        """
        self.tsurl_list = tsurl_lists
        self.path = path
        self.threadnum = threadnum
        self.key = key
        self.retry_list = []  #重试列表
        self.build_files()  #创建下载路径
        self.gongzuomulu = os.getcwd()



    def div_list(self):
        """
        将ts文件分组再多线程会有更快的下载速度
        :param tsurl_list: ts文件下载地址列表 
        :param threadnum: 需要开启的线程数
        :return: lists为分成threadnum个列表的ts文件下载列表
        """
        threadnum = self.threadnum - 1
        docnum = len(self.tsurl_list)
        lists = []
        if threadnum==0 :
            lists.append(self.tsurl_list)
        else:
            gronum = int(docnum / threadnum)
            for i in range(threadnum):
                t_list = self.tsurl_list[gronum * i:(gronum * i + gronum)]
                lists.append(t_list)
            ts_list = self.tsurl_list[(threadnum - 1) * gronum:-1]
            lists.append(ts_list)
        print("ts分组成功")
        return lists

    def download(self,list,download_path):
        """
        下载，若某个ts下载失败，会添加到rttry_list中
        :param list: ts下载地址列表
        :param download_path: 下载路径
        :return: 
        """
        s = requests.Session()
        s.mount('http://', HTTPAdapter(max_retries=1))
        s.mount('https://', HTTPAdapter(max_retries=1))
        thname = threading.current_thread().getName()

        if len(self.key):
            while len(list) != 0:
                addr = list.pop()
                name = addr.rsplit("/", 1)[-1]  #ts文件名
                cryptor = AES.new(self.key, AES.MODE_CBC, self.key)
                try:
                    res = s.get(addr, timeout=5)
                    with open(download_path + "\\" + name, 'wb') as f:
                        f.write(cryptor.decrypt(res.content))
                        print(name + "下载成功")
                except Exception as e:
                    print(e)
                    self.retry_list.append(addr)
        else:
            while len(list) != 0:
                addr = list.pop()
                name = addr.rsplit("/", 1)[-1]
                try:
                    res = s.get(addr, timeout=5)
                    with open(download_path + "\\" + name, 'wb') as f:
                        f.write(res.content)
                        print(name + "下载成功")
                except Exception as e:
                    print(e)
                    self.retry_list.append(addr)

    def mul_thread_download(self):
        """
        多线程下载
        :return: 返回下载失败的ts列表
        """
        lists = self.div_list()
        length = len(lists)
        threads = []
        for i in range(length):
            th_path = self.path + "\\" + "th-" + str(i)
            tt = threading.Thread(target=self.download, name="th-" + str(i), args=(lists[i],th_path))
            threads.append(tt)
        for t in threads:
            try:
                t.start()
                print(t.getName() + "开启成功")
            except:
                print("线程开启失败")
        for t in threads:
            try:
                t.join()
            except:
                print("线程阻塞失败")
        return self.retry_list


    def build_files(self):
        """
        生成下载路径文件夹
        """
        if not os.path.exists(self.path):
            os.mkdir(self.path)

        for i in range(self.threadnum):
            th_path = self.path + "\\th-" + str(i)
            if not os.path.exists(th_path):
                os.mkdir(th_path)

